﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WinFormLogger.Communication
{
    public class ProtocolParse
    {
        public byte[] Header { get; set; }
        public byte[] Footer { get; set; }

        protected List<byte> buffer = new List<byte>();
        public readonly object parseLock = new object();

        public event EventHandler<byte[]> MessageReceive;
        public ProtocolParse(byte[] header, byte[] footer)
        {
            if (header == null && footer == null)
            {
                throw new ArgumentNullException("包头包尾不能为空");
            }
            Header = header;
            Footer = footer;
        }

        public ProtocolParse()
        {
            
        }
        protected virtual void OnMessageReceive(byte[] packet)
        {
            MessageReceive?.Invoke(this, packet);
        }

        /// <summary>
        /// 打包数据，为数据添加包头保包尾
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public byte[] WrapData(byte[] data) 
        {
            if(data == null) 
                throw new ArgumentNullException(nameof(data));
            int headLength = Header?.Length ?? 0;
            int footLength = Footer?.Length ?? 0;
            byte[] result = new byte[headLength + data.Length + footLength];
            if (Header != null) Array.Copy(Header, 0,result, 0, headLength);
            Array.Copy(data, 0, result, headLength, data.Length);
            if (Footer != null) Array.Copy(Footer, 0, result, headLength + data.Length, footLength);
            return result;
        }
        /// <summary>
        /// 解析接收到的数据
        /// </summary>
        /// <param name="data"></param>
        public virtual void ParseData(byte[] data)
        {
            if (data == null || data.Length==0)
                return ;
            lock (parseLock)
            {
                //添加到缓冲区
                buffer.AddRange(data);

                //处理缓冲区逻辑
                ProcessBuffer();
            }
        }

        protected virtual void ProcessBuffer()
        {
            //缓冲区大于头尾长度就循环
            while (buffer.Count>=(Header.Length+Footer.Length))
            {
                //寻找包头
                int headerIndex = FindSequence(buffer, Header);
                //没有找到包头
                if (headerIndex == -1) 
                {
                    buffer.Clear();
                    return;
                }
                //寻找包尾
                int footerIndex = FindSequence(buffer, Footer,Header.Length);
                if (footerIndex == -1) 
                {
                    //保留缓冲区等待更多数据
                    return;
                }

                //提取完整数据包(包含包头包尾)
                int packetLength = footerIndex +Footer.Length;
                byte[] packet = buffer.GetRange(0,packetLength).ToArray();
                
                //移除已处理的数据
                buffer.RemoveRange(0,packetLength);

                //触发数据包接收事件
                OnMessageReceive(packet);
            }
        }

        protected int FindSequence(List<byte> source, byte[] sequence,int startIndex = 0)
        {
            if (source.Count - startIndex < sequence.Length)
            {
                return -1;
            }
            try
            {
                for (int i = startIndex; i < source.Count - sequence.Length; i++) 
                {
                    bool found = true;
                    for(int j = 0; j < sequence.Length; j++)
                    {
                        if(source[i+j] != sequence[j])
                        {
                            found = false; 
                            break;
                        }
                        if(found) return i;
                    }
                }
                return -1;
            }
            catch (Exception ex) 
            {
                return -1;
            }
        }

        public void ClearBuffer()
        {
            lock (parseLock) 
            { 
                buffer.Clear();
            } 
        }

        /// <summary>
        /// 提取数据包中的有效负载（移除包头包尾）
        /// </summary>
        /// <param name="packet"></param>
        /// <returns></returns>
        public byte[] ExtractPayload(byte[] packet)
        {
            if(packet == null || packet.Length<(Header.Length + Footer.Length))
            {
                throw new ArgumentException("数据包格式无效",nameof(packet));
            }
            int payloadLength = packet.Length - Header.Length - Footer.Length;
            byte[] payload = new byte[payloadLength];
            Array.Copy(packet,Header.Length,payload,0,payloadLength);
            return payload;
        }
    }
}
